package com.varian.tool.result;

import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.varian.tool.contant.ResultConstant;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;

/**
 * @author ben
 * @since 2024/6/22
 */
@Data
@Schema(title = "通用返回体")
@Accessors(chain = true)
public class R<T> implements IR {

    @Schema(title = "状态码")
    private Integer status;
    @Schema(title = "异常代码")
    private String code;
    @Schema(title = "消息")
    private String message;
    @JsonInclude(JsonInclude.Include.NON_NULL)
    @Schema(title = "承载数据")
    private T data;

    public static <T> R<T> result(Integer status, String code, String message, T data) {
        return new R<T>()
                .setStatus(status)
                .setCode(code)
                .setMessage(message)
                .setData(data);
    }

    public static <T> R<T> result(Result result) {
        return result(result.status(), ResultConstant.FAIL_CODE, result.message(), null);
    }

    public static <T> R<T> result(Result result, String code) {
        return result(result.status(), code, result.message(), null);
    }

    public static <T> R<T> result(Result result, String code, String message) {
        return result(result.status(), code, message, null);
    }

    public static <T> R<T> ok() {
        return result(ResultConstant.OK, ResultConstant.OK_CODE);
    }

    public static <T> R<T> ok(String message) {
        return result(ResultConstant.OK.status(), ResultConstant.OK_CODE, message, null);
    }

    public static <T> R<T> data(T data) {
        return result(ResultConstant.OK.status(), ResultConstant.OK_CODE, ResultConstant.OK.message(), data);
    }

    public static <T> R<T> data(String message, T data) {
        return result(ResultConstant.OK.status(), ResultConstant.OK_CODE, message, data);
    }

    public static <T> R<T> fail() {
        return result(ResultConstant.FAIL, ResultConstant.FAIL_CODE);
    }

    public static <T> R<T> fail(String code, String template, Object... args) {
        return result(ResultConstant.FAIL.status(), code, StrUtil.format(template, args), null);
    }

    public static <T> R<T> serverError() {
        return result(ResultConstant.SERVICE_ERROR);
    }

    public static <T> R<T> serverError(String message) {
        return result(ResultConstant.SERVICE_ERROR, ResultConstant.FAIL_CODE, message);
    }

    public static <T> R<T> status(boolean state) {
        return state ? ok() : fail();
    }

}
